Memory read operations in synchronous memory systems typically involve a timing domain crossing as read data received at the physical signaling interface of a memory controller (the “PHY”) is transferred from logic operated in response to incoming strobe signals to a separately clocked, and thus different timing domain, memory controller core. This timing domain crossing from strobe domain to core-clock domain tends to be complicated by a number of factors, including the need to account for non-uniform strobe domains for different memory ranks (i.e., groups of memory devices that are selected as a unit to output read data onto respective slices of a data path in response to the same read command) as well as phase drift in a given strobe domain over time due to, for example, changes in voltage and temperature. In general, such timing variations are managed by levelizing the PHY-to-core read data transfer, delaying lower-latency transactions to match those of longer-latency transactions and to account for worst-case timing drift and timing jitter, thus enabling a rank-independent (and drift-independent) read-data latency from the perspective of the memory controller core.